package logs

import (
	"gitee.com/ChanYeung/go-utils/env"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"log"
	"os"
	"path/filepath"
	"sync"
)

var globalLogger *zap.Logger
var defaultLogFile = "logs/all.log"
var defaultErrLogFile = "logs/error.log"
var initOnceLk = sync.Once{}

func init() {
	setLogger(nil)
}

//可以将 zap库的初始化 进行封包，使用时不再进行变量传递，做到开箱即用，参考如下方案 类似go原生log库
//https://tonybai.com/2021/07/14/uber-zap-advanced-usage/
func setLogger(config *zap.Config) {
	var err error
	var loggerConfig zap.Config
	if config == nil {
		//默认控制输出
		if env.IsProduct() || env.IsDev() {
			/**
			Level:       NewAtomicLevelAt(InfoLevel),
			Development: false,
			Sampling: &SamplingConfig{
				Initial:    100,
				Thereafter: 100,
			},
			Encoding:         "json",
			EncoderConfig:    NewProductionEncoderConfig(),
			OutputPaths:      []string{"stderr"},
			ErrorOutputPaths: []string{"stderr"},
			*/
			loggerConfig = zap.NewProductionConfig()
			loggerConfig.OutputPaths = []string{defaultLogFile}
			loggerConfig.ErrorOutputPaths = []string{defaultErrLogFile}
		} else {
			//仅写控制台
			/**
			Level:            NewAtomicLevelAt(DebugLevel),
			Development:      true,
			Encoding:         "console",
			EncoderConfig:    NewDevelopmentEncoderConfig(),
			OutputPaths:      []string{"stderr"},
			ErrorOutputPaths: []string{"stderr"},
			*/
			loggerConfig = zap.NewDevelopmentConfig()
		}
	} else {
		//指定配置
		loggerConfig = *config
	}
	//初始化日志路径
	createDirIfNotExist(loggerConfig.OutputPaths...)
	createDirIfNotExist(loggerConfig.ErrorOutputPaths...)
	logger, err := loggerConfig.Build()
	if err != nil {
		panic(err.Error())
	}
	globalLogger = logger
}
func createDirIfNotExist(fps ...string) {
	for _, fp := range fps {
		dir := filepath.Dir(fp)
		err := os.MkdirAll(dir, 0766)
		if err != nil && !os.IsExist(err) {
			log.Fatal(err)
		}
	}
}

// InitLogger 如果不执行本初始化，则使用默认的配置
func InitLogger(config *zap.Config) {
	initOnceLk.Do(func() {
		setLogger(config)
	})
}

// Log logs a message at the specified level. The message includes any fields
// passed at the log site, as well as any fields accumulated on the logger.
func Log(lvl zapcore.Level, msg string, fields ...zapcore.Field) {
	globalLogger.Log(lvl, msg, fields...)
}

// Debug logs a message at DebugLevel. The message includes any fields passed
// at the log site, as well as any fields accumulated on the logger.
func Debug(msg string, fields ...zapcore.Field) {
	globalLogger.Debug(msg, fields...)
}

// Info logs a message at InfoLevel. The message includes any fields passed
// at the log site, as well as any fields accumulated on the logger.
func Info(msg string, fields ...zapcore.Field) {
	globalLogger.Info(msg, fields...)
}

// Warn logs a message at WarnLevel. The message includes any fields passed
// at the log site, as well as any fields accumulated on the logger.
func Warn(msg string, fields ...zapcore.Field) {
	globalLogger.Warn(msg, fields...)
}

// Error logs a message at ErrorLevel. The message includes any fields passed
// at the log site, as well as any fields accumulated on the logger.
func Error(msg string, fields ...zapcore.Field) {
	globalLogger.Error(msg, fields...)
}

// Panic logs a message at PanicLevel. The message includes any fields passed
// at the log site, as well as any fields accumulated on the logger.
//
// The logger then panics, even if logging at PanicLevel is disabled.
func Panic(msg string, fields ...zapcore.Field) {
	globalLogger.Panic(msg, fields...)

}

// Fatal logs a message at FatalLevel. The message includes any fields passed
// at the log site, as well as any fields accumulated on the logger.
//
// The logger then calls os.Exit(1), even if logging at FatalLevel is
// disabled.
func Fatal(msg string, fields ...zapcore.Field) {
	globalLogger.Fatal(msg, fields...)

}
